package cn.kgc.controller;

import cn.kgc.base.vo.OrderItemVo;
import cn.kgc.base.vo.OrderVo;
import cn.kgc.base.vo.UmsMemberReceiveAddressVo;
import cn.kgc.client.CartFeignClient;
import cn.kgc.client.UmsFeignClient;
import cn.kgc.commons.exception.HttpException;
import cn.kgc.commons.util.RedisUtil;
import cn.kgc.commons.util.UserContextHolder;
import cn.kgc.commons.vo.Result;
import cn.kgc.constant.OrderConstant;
import cn.kgc.entity.OmsOrder;
import cn.kgc.service.OmsOrderService;
import cn.kgc.service.OrderService;
import cn.kgc.vo.OrderConfirmVo;
import cn.kgc.vo.OrderSubmitVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import javafx.scene.chart.ValueAxis;
import org.aspectj.weaver.ast.Or;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * <p></p>
 *
 *
 * vo包：在页面上展示的数据
 *
 * @author 李孟鸠
 * @Date: 2023年01月02日9:41
 */
@RestController
@Api(tags = "订单接口")
@RequestMapping("/order")
public class OmsController {
    //1 获得订单的详细信息（多个收货地址（用户服务中获得）
    //  购物车中选中的多个商品（购物车服务中获得）  应付金额  总金额）

    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    @Resource
    private UmsFeignClient umsFeignClient;

    @Resource
    private CartFeignClient cartFeignClient;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private OrderService orderService;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private OmsOrderService omsOrderService;

    //todo 根据订单的编号获得订单的状态

    @GetMapping("/getOrderVo")
    @ApiOperation(value = "根据订单的编号获得订单的状态",httpMethod = "GET",response = Result.class)
    @ApiImplicitParam(name="orderSn",value = "订单编号",dataType = "string",paramType = "query")
    @CrossOrigin
    public OrderVo getOrderVo(@RequestParam(name = "orderSn") String orderSn){
      LambdaQueryWrapper<OmsOrder>lambdaQueryWrapper=new LambdaQueryWrapper<>();
      lambdaQueryWrapper.eq(OmsOrder::getOrderSn,orderSn);
        OmsOrder omsOrder = omsOrderService.getOne(lambdaQueryWrapper);
        OrderVo orderVo =new OrderVo();
        BeanUtils.copyProperties(omsOrder,orderVo);
        return  orderVo;
    }



    @GetMapping("/getOrderConfirm")
    @ApiOperation(value = "获得订单确认信息",httpMethod ="GET",
            response = Result.class)
    @CrossOrigin
    public OrderConfirmVo getOrderConfirm(){
        //登录用户的ID
//        Long userId=1L;
        Long userId = Long.valueOf(UserContextHolder.getInstance().getUserId());

        OrderConfirmVo orderConfirmVo=new OrderConfirmVo();
        //获得登录用户的收获地址（远程接口）

        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
            System.out.println("获得登录用户的收获地址（远程接口）");
            Result<List<UmsMemberReceiveAddressVo>> result =
                    umsFeignClient.getUmsMemberReceiveAddress(userId);
            if (result.getData()!=null){
                orderConfirmVo.setAddressVoList(result.getData());
            }
        }, threadPoolExecutor);

        //获得登录用户的购物车中选中的商品信息（远程接口）
        CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
            Result<List<OrderItemVo>> result = cartFeignClient.getOrderItemVo(userId);
            if (result.getData()!=null){ //如果服务没有降级，保存订单对应的商品信息
                orderConfirmVo.setCartItemVoList(result.getData());
                //总价
                BigDecimal totalPrice=new BigDecimal(0);
                //订单中的商品价格累加
                List<OrderItemVo> orderItemVoList = orderConfirmVo.getCartItemVoList();
                for (OrderItemVo orderItemVo : orderItemVoList) {
                    totalPrice=totalPrice.add(orderItemVo.getTotalPrice());
                }
                orderConfirmVo.setPayTotalPrice(totalPrice);  //应付金额
                orderConfirmVo.setTotalPrice(totalPrice); //总金额
            }
        }, threadPoolExecutor);

        try {
            //异步任务执行完成以后，程序在向下执行
            CompletableFuture.allOf(future1,future2).get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        //生成令牌
        String token= UUID.randomUUID().toString().replaceAll("-","");
        //将令牌保存到Redis中
        String orderTokenKey= OrderConstant.ORDER_TOKEN_PREFIX+token;
        redisUtil.set(orderTokenKey,token,OrderConstant.ORDER_TOKEN_TIME, TimeUnit.MINUTES);

        //返回令牌
        orderConfirmVo.setOrderToken(token);
        return orderConfirmVo;
    }



    //2 生成订单:接口幂等性
    //(1) 一些基本的sql语句幂等性
    // select sql语句没有幂等性问题
    // delete sql语句没有幂等性问题
    // update sql语句幂等性,乐观锁
    // insert sql语句幂等性,设置某些字段是唯一的
    //(2)实现接口幂等性,使用令牌的方式
    @ApiOperation(value = "生成订单,返回订单编号",httpMethod = "POST",
            produces = "application/json;charset=utf-8",response = Result.class)
    @PostMapping("/generateOrder")
    @CrossOrigin
    public Result<String> generateOrder(@RequestBody OrderSubmitVO orderSubmitVO){
        //保证接口幂等性
        String orderToken= orderSubmitVO.getOrderToken();
        String orderTokenKey=OrderConstant.ORDER_TOKEN_PREFIX+orderToken;
        //判断接口幂等性
        boolean flag=redisUtil.execute(orderTokenKey,orderToken);
        if(!flag){
            throw new HttpException(50001,
                    HttpStatus.INTERNAL_SERVER_ERROR.value());
        }
        long memberId=Long.parseLong(UserContextHolder.getInstance().getUserId());
        String memberName=UserContextHolder.getInstance().getUserName();

        //保存订单相关信息
        String orderSn=orderService
                .generateOrderInfo(orderSubmitVO,memberId,memberName);

        OmsOrder omsOrder=new OmsOrder();
        omsOrder.setOrderSn(orderSn); //订单编号
        if (orderSn!=null){
            rabbitTemplate.convertAndSend(OrderConstant.ORDER_EXCHANGE,
                    OrderConstant.CREATE_ORDER_ROUTING_KEY,omsOrder);
        }

        return Result.ok(orderSn,
                "http://mall-oms/order/generateOrder");
    }

}
